<html>
<head><meta charset="utf-8"><title>purity of `const fn` vs effect systems · t-compiler/const-eval · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/index.html">t-compiler/const-eval</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html">purity of `const fn` vs effect systems</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="218429881"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218429881" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218429881">(Dec 01 2020 at 14:39)</a>:</h4>
<p>As noted by <span class="user-mention" data-user-id="120791">@RalfJ</span> in <a href="https://github.com/rust-lang/rust/issues/79597">#79597</a> if we allow <code>const fn</code> to perform heap allocations, we can have a const fn that, even if it has no arguments, will return a new value (pointer to new heap allocation) with every invocation. Right now, there is no difference between a <code>const FOO: T = ...;</code>and a <code>const fn foo() -&gt; T { ... }</code> in terms of how it is evaluated.</p>



<a name="218430255"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430255" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430255">(Dec 01 2020 at 14:42)</a>:</h4>
<p>One way to solve this problem is to not allow <code>const fn</code> to use <code>GlobalAlloc</code> directly. The only way this type may occur is via generics. This means that <em>all</em> <code>const fn</code> that transitively do any kind of heap stuff need to have a generic parameter for the allocator. <code>const</code>/<code>static</code> items will then be able to invoke <code>const fn</code> and pass the <code>Global</code> allocator argument to them</p>



<a name="218430432"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430432" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430432">(Dec 01 2020 at 14:44)</a>:</h4>
<p>I don't see how that helps</p>



<a name="218430479"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430479" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430479">(Dec 01 2020 at 14:44)</a>:</h4>
<p>We can then make const functions that have a generic parameter for the allocator type impure. This would make <code>AllocRef</code> a lang item</p>



<a name="218430483"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430483" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430483">(Dec 01 2020 at 14:44)</a>:</h4>
<p>we still end up with a function that has signature <code>const fn() -&gt; T</code> (after instantiating the generic parameter) that is not pure</p>



<a name="218430527"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430527" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430527">(Dec 01 2020 at 14:44)</a>:</h4>
<p>this is a syntactic hack that falls short once you go higher-order</p>



<a name="218430574"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430574" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430574">(Dec 01 2020 at 14:45)</a>:</h4>
<p>you mean when you put it in a function pointer?</p>



<a name="218430621"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430621" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430621">(Dec 01 2020 at 14:45)</a>:</h4>
<p>yes, or a trait object</p>



<a name="218430782"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430782" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430782">(Dec 01 2020 at 14:46)</a>:</h4>
<p>we'll always know whether the function pointer had a generic heap argument when looking at the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/enum.GlobalAlloc.html"><code>GlobalAlloc::Function</code></a></p>



<a name="218430798"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218430798" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218430798">(Dec 01 2020 at 14:46)</a>:</h4>
<p>or are you talking about runtime?</p>



<a name="218431808"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218431808" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218431808">(Dec 01 2020 at 14:54)</a>:</h4>
<p>I am talking about statically in the type system</p>



<a name="218431868"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218431868" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218431868">(Dec 01 2020 at 14:54)</a>:</h4>
<p>one point of <code>const fn</code> being pure is that unsafe code can use the type<code>const fn()</code> and then rely, for safety, on the fact that this function is pure</p>



<a name="218432782"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218432782" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> oli <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218432782">(Dec 01 2020 at 15:01)</a>:</h4>
<p>So... I have one more card in my sleeve that I hoped I wouldn't have to use. It's probably not feasible, but here we go:</p>
<p>Just like <code>alloc_in</code> is what actually allows arbitrary allocators and not just those with <code>Default</code> bounds like <code>Global</code>, we can make <code>ConstGlobal</code> not be <code>ZST</code> and thus require that all function pass this value down. We then ensure that you can only create values of type <code>ConstGlobal</code> within <code>const</code>/<code>static</code> items, but not within <code>const fn</code>. We'll just need to figure out how to prevent you from returning values of type <code>ConstGlobal</code> in the final value of a <code>const</code> item, otherwise a <code>const fn</code> can just use a <code>const</code> item that gives you a <code>ConstGlobal</code> value</p>



<a name="218444625"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/146212-t-compiler/const-eval/topic/purity%20of%20%60const%20fn%60%20vs%20effect%20systems/near/218444625" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/146212-t-compiler/const-eval/topic/purity.20of.20.60const.20fn.60.20vs.20effect.20systems.html#218444625">(Dec 01 2020 at 16:18)</a>:</h4>
<p>hm... interesting. I think you just described a lightweight effect system :D</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>